﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using Microsoft.Win32;
using System.Windows;
using System.Xml;
using SHomeWorkshop.LunarTools;
using System.Windows.Controls;

namespace SHomeWorkshop.LunarMind.Commands
{
    /// <summary>
    /// 以此类为模板，制作自定义命令类
    ///     共需要修改１０处！！！
    /// ==============================
    /// 
    /// 添加关系命令。
    /// ★①，修改类名。
    /// </summary>
    public static class AddRelationCommand
    {
        private static RoutedUICommand routedUICmd;//创建私有字段

        public static RoutedUICommand RoutedUICmd//创建只读静态属性
        {
            get { return routedUICmd; }
        }

        /// <summary>
        /// ★②，修改静态构造方法名。
        /// </summary>
        static AddRelationCommand()//类型构造器
        {
            //★③，修改两个字符串参数名。★④以及第三个参数的类型名。
            routedUICmd = new RoutedUICommand("AddRelationCommand", "AddRelationCommand",
                typeof(AddRelationCommand),//创建RoutedUICommand对象
                new InputGestureCollection() 
                { 
                    //★⑤，修改此处两个参数，以便挂接快捷键。
                    new KeyGesture(Key.R,ModifierKeys.Alt,"Alt+R")
                });

            cmdBinding.Command = routedUICmd;
            cmdBinding.CanExecute += new CanExecuteRoutedEventHandler(cmdBinding_CanExecute);
            cmdBinding.Executed += new ExecutedRoutedEventHandler(cmdBinding_Executed);
        }

        private static CommandBinding cmdBinding = new CommandBinding();

        public static CommandBinding CmdBinding
        {
            get { return cmdBinding; }
        }

        static void cmdBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            //★⑦，修改此方法的实现。

            AddRelation();
        }

        private static void AddRelation()
        {
            if (Globals.SelectedTitlesList.Count != 2 ||
               Globals.MainWindow.MainSelectedTitle == null ||
               Globals.SelectedTitlesList.Contains(Globals.MainWindow.MainSelectedTitle) == false) return;

            int indexOfMainSelectedTitle = Globals.SelectedTitlesList.IndexOf(Globals.MainWindow.MainSelectedTitle);
            Title endTitle = Globals.MainWindow.MainSelectedTitle;
            Title startTitle = indexOfMainSelectedTitle == 0 ? Globals.SelectedTitlesList[1] : Globals.SelectedTitlesList[0];

            AddRelation(startTitle, endTitle);
        }

        /// <summary>
        /// 直接在指定的两个Title之间添加关系线。
        /// </summary>
        /// <param name="startTitle"></param>
        /// <param name="endTitle"></param>
        /// <param name="outXml">要插入的关系线的OutXml</param>
        /// <param name="modifiInfo">mi的ModifingName字符串</param>
        public static void AddRelation(Title startTitle, Title endTitle,
            XmlNode relationNode = null, string modifiInfo = null)
        {
            if (startTitle == null || endTitle == null) return;

            string minfo = null;
            if (modifiInfo == null)
            {
                minfo = "添加关系线";
            }
            else
            {
                minfo = modifiInfo;
            }

            ModifingItem mi = new ModifingItem() { ModifingName = minfo };

            Relation relation = new Relation(Globals.MainWindow, startTitle, endTitle);

            XmlNode relationSetNode = Globals.MainWindow.MainXmlDocument.DocumentElement.SelectSingleNode("RelationSet");
            if (relationSetNode == null)
            {
                relationSetNode = Globals.MainWindow.MainXmlDocument.DocumentElement.AppendXml("<RelationSet />");
            }

            XmlNode newNode;
            if (relationNode != null)
            {
                newNode = relationSetNode.AppendXml(relationNode.OuterXml);
            }
            else
            {
                newNode = relationSetNode.AppendXml("<Relation />");
            }

            relation.XmlData = newNode;

            //计算出需要的两个控制点的坐标。

            ResetRelationLocation(relation, startTitle, endTitle);

            relation.StartTitleID = relation.StartTitle.ID;
            relation.EndTitleID = relation.EndTitle.ID;
            relation.XmlData.SetAttribute("ID", relation.ID);//调用ReBuildID()则会生成一个新ID并写入后台Xml。

            Action actAddRelation = new Action(relation.ID,
                -1, relation.GetType().Name, "AddRelation", relation.StartTitleID, relation.XmlData.OuterXml,
                ActionType.AddRelation, relation.EndTitleID);

            Globals.MainWindow.mainCanvas.Children.Add(relation);//一些初始化必须在此行之后才可进行。这涉及布局。

            //relation.CommentText = "这是备注文本";//在添加之前，无法确定TextBlock的尺寸。因而会导致显示不准确。

            relation.RefreshLocation();

            mi.Add(actAddRelation);

            Globals.MainWindow.Do(mi);
            Globals.MainWindow.IsModified = true;

            Globals.MainWindow.SelectedRelation = relation;
        }

        /// <summary>
        /// 重置Relation的两个控制点的位置。
        /// </summary>
        /// <param name="relation"></param>
        /// <param name="startTitle"></param>
        /// <param name="endTitle"></param>
        internal static void ResetRelationLocation(Relation relation, Title startTitle, Title endTitle)
        {
            if (relation == null || startTitle == null || endTitle == null) return;
            if (relation.StartTitleID != startTitle.ID || relation.EndTitleID != endTitle.ID) return;

            double endIndentWidth =
                (endTitle.Direction == TitleDirection.Right) ?
                endTitle.IndentWidth :
                -endTitle.IndentWidth;

            double startIndentWidth =
                (startTitle.Direction == TitleDirection.Right) ?
                startTitle.IndentWidth :
                -startTitle.IndentWidth;

            Rect startRect = new Rect(startTitle.LeftTop.X + startTitle.MainBorder.Margin.Left + startIndentWidth,
                startTitle.LeftTop.Y + startTitle.MainBorder.Margin.Top,
                startTitle.ActualWidth - startTitle.MainBorder.Margin.Left - startTitle.MainBorder.Margin.Right,
                startTitle.ActualHeight - startTitle.MainBorder.Margin.Top - startTitle.MainBorder.Margin.Bottom);

            Rect endRect = new Rect(endTitle.LeftTop.X + endTitle.MainBorder.Margin.Left + endIndentWidth,
                endTitle.LeftTop.Y + endTitle.MainBorder.Margin.Top,
                endTitle.ActualWidth - endTitle.MainBorder.Margin.Left - endTitle.MainBorder.Margin.Right,
                endTitle.ActualHeight - endTitle.MainBorder.Margin.Top - endTitle.MainBorder.Margin.Bottom);

            Point startCenter = new Point(startRect.Left + (startRect.Right - startRect.Left) / 2,
                startRect.Top + (startRect.Bottom - startRect.Top) / 2);

            Point endCenter = new Point(endRect.Left + (endRect.Right - endRect.Left) / 2,
                endRect.Top + (endRect.Bottom - endRect.Top) / 2);

            PointToRect.ArrowPoints aptStart = PointToRect.GetCrossPointToRect(startRect, endCenter);
            PointToRect.ArrowPoints aptEnd = PointToRect.GetCrossPointToRect(endRect, startCenter);

            //这个是两个交点连线的中心点的绝对坐标。
            Point ctrlCenter = new Point(
                aptStart.Top.X + (aptEnd.Top.X - aptStart.Top.X) / 2,
                aptStart.Top.Y + (aptEnd.Top.Y - aptStart.Top.Y) / 2
                );

            //这里要求的是相对于标题中心点的坐标。
            //要注意转换成相对坐标。
            Point startControl = new Point(
                 ctrlCenter.X - (aptEnd.Top.X - aptStart.Top.X) / 4 - startCenter.X,
                 ctrlCenter.Y - (aptEnd.Top.Y - aptStart.Top.Y) / 4 - startCenter.Y
                );

            Point endControl = new Point(
                   ctrlCenter.X + (aptEnd.Top.X - aptStart.Top.X) / 4 - endCenter.X,
                   ctrlCenter.Y + (aptEnd.Top.Y - aptStart.Top.Y) / 4 - endCenter.Y
                );

            relation.StartCtrlPoint = startControl;
            relation.EndCtrlPoint = endControl;
        }

        static void cmdBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            //★⑧，修改此方法的实现。

            if (Globals.SelectedTitlesList.Count == 2 &&
                Globals.MainWindow.MainSelectedTitle != null &&
                Globals.SelectedTitlesList.Contains(Globals.MainWindow.MainSelectedTitle))
            {
                e.CanExecute = true;
            }
            else e.CanExecute = false;
        }
    }
}
